#!/bin/bash

# 设置默认IP地址和密码
DEFAULT_IP=$(curl ifconfig.me)
DEFAULT_PASSWORD=$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 10)
docker_cert_path="/etc/docker/certs"
port_number="2221"

function generate() {
  echo "开始生成docker远程访问证书"
  echo "请输入Docker证书保存路劲路径（默认为 $docker_cert_path ）："
  read -r docker_cert_path_input
  if [[ -n "$docker_cert_path_input" ]]; then
    # 创建certs文件夹
    docker_cert_path=$docker_cert_path_input
  fi
  mkdir -pv $docker_cert_path
  cd $docker_cert_path
  docker_cert_path=$(pwd)

  #ip 录入
  echo "请输入访问Docker的Ip或域名:默认为 $DEFAULT_IP）"
  read -r docker_ip_input
  if [[ -n "$docker_ip_input" ]]; then
    DEFAULT_IP="$docker_ip_input"
  fi

  echo "请输入端口号（默认为 $port_number ）："
  read -r port_number_input
  if [[ -n "$port_number_input" ]]; then
    port_number="$port_number_input"
  fi

  #证书密码录入
  echo "请输入证书的密码:(随机密码：$DEFAULT_PASSWORD)"
  read -r cert_password_input
  if [[ -n "$cert_password_input" ]]; then
    DEFAULT_PASSWORD="$cert_password_input"
  fi

  # 生成CA私钥
  openssl genrsa -aes256 -passout pass:"$DEFAULT_PASSWORD" -out ca-key.pem 4096

  # 生成CA证书
  openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem -passin pass:"$DEFAULT_PASSWORD" -subj "/C=US/ST=State/L=City/O=Company/OU=Department/CN=YourNameOrServerHostname/emailAddress=youremail@example.com"

  # 生成服务器私钥
  openssl genrsa -out server-key.pem 4096

  # 生成服务器证书签名请求
  openssl req -subj "/CN=${DEFAULT_IP}" -sha256 -new -key server-key.pem -out server.csr

  # 配置白名单
  echo "subjectAltName = IP:0.0.0.0,IP:${DEFAULT_IP},IP:127.0.0.1" >>extfile.cnf

  # 将Docker守护程序密钥的扩展使用属性设置为仅用于服务器身份验证
  echo "extendedKeyUsage = serverAuth" >>extfile.cnf

  # 生成服务器证书
  openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf -passin pass:"$DEFAULT_PASSWORD"

  # 生成客户端私钥
  openssl genrsa -out key.pem 4096

  # 生成客户端证书签名请求
  openssl req -subj "/CN=${DEFAULT_IP}" -new -key key.pem -out client.csr

  # 创建客户端扩展配置文件
  echo "extendedKeyUsage = clientAuth" >extfile-client.cnf

  # 生成客户端证书
  openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile extfile-client.cnf -passin pass:"$DEFAULT_PASSWORD"

  # 删除临时文件
  rm -rf client.csr server.csr extfile.cnf extfile-client.cnf

  # 修改私钥权限
  chmod -v 0400 ca-key.pem key.pem server-key.pem

  # 修改公钥权限
  chmod -v 0444 ca.pem server-cert.pem cert.pem

  # 打包客户端证书
  tar -czvf client-certs.tar.gz ca.pem cert.pem key.pem

  #删除原文件
  rm -rf  cert.pem key.pem

  echo "客户端证书地址:$docker_cert_path/client-certs.tar.gz"
}

function add_docker_line() {
  echo "准备开启docker远程访问"
  file_path="/etc/systemd/system/docker.service"
  sudo cp /lib/systemd/system/docker.service $file_path
  # 定义原始行和替换行
  original_line="ExecStart=/usr/bin/dockerd"
  commented_line="# $original_line"
  # 定义替换行
  new_line="ExecStart=/usr/bin/dockerd --tlsverify \
	--tlscacert=${docker_cert_path}/ca.pem \
	--tlscert=${docker_cert_path}/server-cert.pem \
	--tlskey=${docker_cert_path}/server-key.pem \
	-H tcp://0.0.0.0:$port_number \
	-H unix:///var/run/docker.sock \
	-H fd:// --containerd=/run/containerd/containerd.sock"

  # 注释原始行
  sudo sed -i "s|$original_line|$commented_line|g" "$file_path"

  # 在文件中查找匹配模式的行
  line_number=$(grep -n "^$commented_line" "$file_path" | cut -d':' -f1)
  if [ -n "$line_number" ]; then
    # 在该行下插入新的行
    sudo sed -i "${line_number}a $new_line" "$file_path"

    echo "已开启docker远程访问"
  else
    echo "未找到匹配的行。"
  fi
}

function restart_docker() {
  echo "准备重启docker服务"
  systemctl daemon-reload
  systemctl restart docker
  echo "docker服务重启完成"
}

generate
add_docker_line
restart_docker
echo "docker远程连接信息"
echo "连接地址：https://$DEFAULT_IP:$port_number"
echo "连接证书：$docker_cert_path/client-certs.tar.gz"
